
#include "../Header/cModel.h"
#include "../Header/ShaderObject.h"
#include "../Header/glErrorUtil.h"
#include "../Header/misc.h"
#include "../Header/misc/nvImage.h"

///
/// fileName		Model's filename
/// texFileName		texture model filename
///
cModel::cModel(char* fileName, char* diffuseTex, char *bumpMapTex)
{		
	if (loadModelFromFile( fileName )) {
		computeNormals();
		computeTangents();

		// rescale the  bounding box  to 1.0
		//model->rescale(1.0f);
		// make the model efficient for rendering with vertex arrays
		compileModel( nv::Model::eptAll);
		
		glGenBuffers( 1, &vbo);
		// load the vertex data for the compiled model
		glBindBuffer( GL_ARRAY_BUFFER, vbo);
		glBufferData( GL_ARRAY_BUFFER, getCompiledVertexSize() * getCompiledVertexCount() * sizeof(float), getCompiledVertices(), GL_STATIC_DRAW);

		glGenBuffers( 1, &indexBuffer);
		//load the index data for the compiled model
		glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
		glBufferData( GL_ELEMENT_ARRAY_BUFFER, getCompiledIndexCount() * sizeof(GLuint), getCompiledIndices(), GL_STATIC_DRAW);
	}
	else {
		//FREE_MEMORY	(model);
		printf( "Error: Failed to load model: %s\n", fileName);
		exit(-1);
	}
	if (diffuseTex)
		diffuseTexId = loadDDS(diffuseTex);
	if (bumpMapTex)
		bumpMapTexId = loadDDS(bumpMapTex);
}

unsigned int cModel::loadDDS(char *fileName)
{
	unsigned int id;
	int i, w, h;
	nv::Image tex;

	if(!tex.loadImageFromFile(fileName))
	{
		fprintf(stdout, "%s not found.\n",fileName);
		exit(-1);
	}
	w = tex.getWidth();
	h = tex.getHeight();

	glGenTextures(1, &id);
	glBindTexture(GL_TEXTURE_2D, id);
	glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
		
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	
	for (i=0;i<tex.getMipLevels() && (w || h);i++)
	{
		if (w == 0)
			w = 1;
		if (h == 0)
			h = 1;

		CheckErrorsGL("loadDDS BEGIN : Creating MIP MAPS");
			glCompressedTexImage2DARB( GL_TEXTURE_2D, i, tex.getInternalFormat(), w, h, 0, tex.getImageSize(i), tex.getLevel(i));
		CheckErrorsGL("loadDDS END : Creating MIP MAPS");

		w >>= 1;
		h >>= 1;
	}
	return id;
}



cModel::~cModel()
{
	FREE_VBO(vbo);
	FREE_VBO(indexBuffer);
	
} 

void cModel::draw(ShaderObject *shader)
{

	//const float *normals = getNormals();
	//CheckErrorsGL("cModel::draw BEGIN");
	glEnable(GL_TEXTURE_2D);
	glActiveTexture (GL_TEXTURE0);
	glBindTexture (GL_TEXTURE_2D, diffuseTexId);

	glBindBuffer( GL_ARRAY_BUFFER, vbo);
	glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexBuffer);

		glVertexPointer( getPositionSize(), GL_FLOAT, getCompiledVertexSize() * sizeof(float), 0);
		glNormalPointer( GL_FLOAT, getCompiledVertexSize() * sizeof(float), (void*)(getCompiledNormalOffset() * sizeof(float)));
		glTexCoordPointer(getTexCoordSize(), GL_FLOAT, getCompiledVertexSize()*sizeof(float), (void*)(getCompiledTexCoordOffset()*sizeof(float)));
		
		glEnableClientState( GL_VERTEX_ARRAY);
		glEnableClientState( GL_NORMAL_ARRAY);
		//glClientActiveTexture(GL_TEXTURE0);
		glEnableClientState( GL_TEXTURE_COORD_ARRAY);

		if (shader) 
		{
			shader->activate();
			shader->setUniformi("diffuseTex",0);
				glDrawElements( GL_TRIANGLES, getCompiledIndexCount(), GL_UNSIGNED_INT, 0);
			shader->deactivate();
		} else
		{
			glDrawElements( GL_TRIANGLES, getCompiledIndexCount(), GL_UNSIGNED_INT, 0);
		}

		glDisableClientState( GL_VERTEX_ARRAY);
		glDisableClientState( GL_NORMAL_ARRAY);
		glDisableClientState( GL_TEXTURE_COORD_ARRAY);

	glBindBuffer( GL_ARRAY_BUFFER, 0);
	glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0);

	glBindTexture (GL_TEXTURE_2D, 0);

	//CheckErrorsGL("cModel::draw END");	
}
